package com.superman.util.base.map;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * FIFO(first in first out) 先进先出
 * 元素不停的加入缓存直到缓存满为止，当缓存满时，删除先入的缓存（链表首部对象）
 * 优点：简单快速
 * 缺点：不灵活，不能保证最常用的对象总是被保留
 * Author: superman
 * Date: 2024/5/22 11:06
 */
public class ConcurrentFIFOHashMap<K, V> extends ConcurrentHashMap<K, V> {

    /**
     * 缓存容量
     */
    private final int capacity;
    /**
     * 队列，存储所有的key
     */
    private final ConcurrentLinkedDeque<K> queue = new ConcurrentLinkedDeque<>();
    /**
     * 锁对象
     */
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * 构造
     *
     * @param capacity 容量
     */
    public ConcurrentFIFOHashMap(int capacity) {
        this.capacity = Math.abs(capacity);
    }

    @Override
    public V put(K key, V value) {
        // 写锁, 保证key队列和map一致
        this.lock.writeLock().lock();
        try {
            // 达到容量上限，从队列中获取第一个key，从map中删除对应键值对
            if (super.size() >= this.capacity) {
                K firstKey = this.queue.pollFirst();
                if (firstKey != null) {
                    super.remove(firstKey);
                }
            }
            // 将指定的元素插入到这个队列的尾部
            this.queue.offer(key);
            // 添加 键值对
            super.put(key, value);
            return value;
        } finally {
            this.lock.writeLock().unlock();
        }
    }


}
